import { Injectable, Inject } from "@angular/core";
import {
  ISelectSymbolResponse,
  IMu,
  IZi,
  IQuerySymbol
} from "@/trade/store/models/trade";
import big from "@assets/lib/big";

@Injectable({
  providedIn: "root"
})
export class UtilsService {
  timer;

  depth: Depth = null;

  constructor(@Inject("ConfigService") private configService) {
    this.depth = new Depth(configService);
  }

  isNumber(v) {
    return Object.prototype.toString.call(v) === "[object Number]";
  }

  isEmpty(o) {
    // if(){
    // }
  }

  isUndefined(o: any) {
    return Object.prototype.toString.call(o) === "[object Undefined]";
  }

  isString(o: any) {
    return Object.prototype.toString.call(o) === "[object String]";
  }

  isEmptyObj(o) {
    return JSON.stringify(o) === "{}";
  }

  isEmptyArr(o) {
    return JSON.stringify(o) === "[]";
  }

  debounce(fn: Function, time: number = 1000) {
    if (this.timer) {
      clearTimeout(this.timer);
    }
    this.timer = setTimeout(() => {
      fn();
      clearTimeout(this.timer);
    }, time);
  }
  splitQuerySymbol(symbol): IQuerySymbol {
    const arr = symbol.split("_");
    return {
      zi: arr[0],
      mu: arr[1]
    };
  }
  unsub(sub$: any) {
    for (const key in sub$) {
      if (sub$.hasOwnProperty(key)) {
        const item = sub$[key];
        if (!!item) {
          item.unsubscribe();
        }
      }
    }
  }
  formatPoint(arr: Array<any>) {
    return arr.slice().map(d => {
      const ret = {};
      for (const key in d) {
        if (d.hasOwnProperty(key)) {
          ret[key] = big.toFixed(d[key], this.configService.point);
        }
      }
      return {
        ...ret
      };
    });
  }
  formatNumPoint(num: string): string {
    return big.toFixed(num, this.configService.point);
  }
}

export interface IDepthItem {
  price: string;
  amount: string;
  total: string;
  percent: string;
}
class Depth {
  private configService = null;
  constructor(configService) {
    this.configService = configService;
  }
  formatBuy(arr: Array<IDepthItem>): Array<IDepthItem> {
    const a: Array<IDepthItem> = arr
      .slice()
      .map(d => {
        if (big.isLt(big.toFixed(d.amount, this.configService.point), "0")) {
          return {
            ...d,
            amount: big.toFixed("0", this.configService.point)
          };
        }
        return {
          ...d
        };
      })
      .sort((pre: IDepthItem, next: IDepthItem) => {
        return Number(
          big.minus(
            big.toFixed(next.price, this.configService.point),
            big.toFixed(pre.price, this.configService.point)
          )
        );
      });

    const item = a
      .slice()
      .sort((pre: IDepthItem, next: IDepthItem) => {
        return Number(
          big.minus(
            big.toFixed(next.price, this.configService.point),
            big.toFixed(pre.price, this.configService.point)
          )
        );
      })
      .reduce(
        (pre: IDepthItem, cur: IDepthItem, index: number) => {
          const total = big.toFixed(
            big.plus(pre.total, cur.amount),
            this.configService.point
          );

          a[index].total = total;

          return {
            price: big.toFixed(cur.price, this.configService.point),
            amount: big.toFixed(cur.amount, this.configService.point),
            total,
            percent: cur.percent
          };
        },
        {
          price: big.toFixed("0", this.configService.point),
          amount: big.toFixed("0", this.configService.point),
          total: big.toFixed("0", this.configService.point),
          percent: big.toFixed("0", this.configService.point)
        }
      );

    const max = a.slice().sort((pre: IDepthItem, next: IDepthItem) => {
      return Number(
        big.minus(
          big.toFixed(next.amount, this.configService.point),
          big.toFixed(pre.amount, this.configService.point)
        )
      );
    });

    return a
      .slice()
      .map((d: IDepthItem) => {
        return {
          ...d,
          percent: `${Number(big.toFixed(big.div(d.amount, max[0].amount), 2)) *
            100}%`
        };
      })
      .filter(d => {
        return Number(d.amount) !== 0;
      });
  }

  formatSell(arr: Array<IDepthItem>): Array<IDepthItem> {
    const a: Array<IDepthItem> = arr
      .slice()
      .map(d => {
        if (big.isLt(big.toFixed(d.amount, this.configService.point), "0")) {
          return {
            ...d,
            amount: big.toFixed("0", this.configService.point)
          };
        }
        return {
          ...d
        };
      })
      .sort((pre: IDepthItem, next: IDepthItem) => {
        return Number(
          big.minus(
            big.toFixed(pre.price, this.configService.point),
            big.toFixed(next.price, this.configService.point)
          )
        );
      });

    const item = a
      .slice()
      .sort((pre: IDepthItem, next: IDepthItem) => {
        return Number(
          big.minus(
            big.toFixed(pre.price, this.configService.point),
            big.toFixed(next.price, this.configService.point)
          )
        );
      })
      .reduce(
        (pre: IDepthItem, cur: IDepthItem, index: number) => {
          const total = big.toFixed(
            big.plus(pre.total, cur.amount),
            this.configService.point
          );

          a[index].total = total;

          return {
            price: big.toFixed(cur.price, this.configService.point),
            amount: big.toFixed(cur.amount, this.configService.point),
            total,
            percent: cur.percent
          };
        },
        {
          price: big.toFixed("0", this.configService.point),
          amount: big.toFixed("0", this.configService.point),
          total: big.toFixed("0", this.configService.point),
          percent: big.toFixed("0", this.configService.point)
        }
      );

    const max = a.slice().sort((pre: IDepthItem, next: IDepthItem) => {
      return Number(
        big.minus(
          big.toFixed(next.amount, this.configService.point),
          big.toFixed(pre.amount, this.configService.point)
        )
      );
    });
    return a
      .slice()
      .map((d: IDepthItem) => {
        return {
          ...d,
          percent: `${Number(big.toFixed(big.div(d.amount, max[0].amount), 2)) *
            100}%`
        };
      })
      .filter(d => {
        return Number(d.amount) !== 0;
      });
    // .sort((pre: IDepthItem, next: IDepthItem) => {
    //   return Number(
    //     big.minus(
    //       big.toFixed(next.price, this.configService.point),
    //       big.toFixed(pre.price, this.configService.point)
    //     )
    //   );
    // });
  }
}
